package com.baizhi.service.impl;

import cn.hutool.core.util.ObjectUtil;
import com.baizhi.dto.Result;
import com.baizhi.dto.UserDTO;
import com.baizhi.entity.SeckillVoucher;
import com.baizhi.entity.VoucherOrder;
import com.baizhi.mapper.SeckillVoucherMapper;
import com.baizhi.service.ISeckillVoucherService;
import com.baizhi.service.IVoucherOrderService;
import com.baizhi.utils.IdGenerator;
import com.baizhi.utils.UserHolder;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Collections;
import java.util.concurrent.*;

/**
 * <p>
 * 秒杀优惠券表，与优惠券是一对一关系 服务实现类
 * </p>
 *
 * @author gange
 * @since 2022-01-04
 */
@Service
public class SeckillVoucherServiceImpl extends ServiceImpl<SeckillVoucherMapper, SeckillVoucher> implements ISeckillVoucherService {
    @Autowired
    private IVoucherOrderService iVoucherOrderService;
    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private IdGenerator idGenerator;
    @Autowired
    private IVoucherOrderService voucherOrderServicel;
    @Autowired
    private ISeckillVoucherService seckillVoucherService;

    private DefaultRedisScript<Long> SECKILL_SCRIPT;
    //阻塞队列
    private BlockingQueue<VoucherOrder> queue = new ArrayBlockingQueue<>(1024);
    //定义出来一个处理阻塞队列的线程池
    ExecutorService threadPool = Executors.newSingleThreadExecutor();
    @PostConstruct
    public void initThreadPoll(){
        //给线程池提交一个任务
        threadPool.submit(()->{
           while (true){
               VoucherOrder order = queue.take();
               //操作数据库
               seckillVoucherService.getResult(order);
           }
        });
    }
    @Transactional
    public void getResult(VoucherOrder order) {
        //	5库存要减一。
        update().setSql("stock=stock-1").eq("voucher_id", order.getVoucherId()).update();
        order.setCreateTime(LocalDateTime.now());
        order.setStatus(1);//刚下单
        //	4订单表生成个订单。
        voucherOrderServicel.save(order);
    }
    @PostConstruct //当spring容器对bean对象创建完毕后会执行一次该方法
    public void initLuaScript(){
        SECKILL_SCRIPT = new DefaultRedisScript<>();
        SECKILL_SCRIPT.setLocation(new ClassPathResource("seckill.lua"));
        SECKILL_SCRIPT.setResultType(Long.class);
    }


    @Override
    public Result seckillVoucher(Long voucherId) {
        //执行lua脚本 判断返回结果
        Long userId = UserHolder.getUser().getId();
        Long result =  (Long) redisTemplate.execute(
                SECKILL_SCRIPT,
                Collections.emptyList(),
                voucherId,userId
        );
        //把long类型转换为int类型
        int resultInt = result.intValue();
        if (resultInt!=0){
            return Result.fail(resultInt==1?"库存不足":"不可重复买");
        }
        //把任务放到阻塞队列里面
        Long orderId = idGenerator.generateId();
        VoucherOrder voucherOrder = new VoucherOrder();
        voucherOrder.setId(orderId);
        voucherOrder.setUserId(userId);
        voucherOrder.setVoucherId(voucherId);
        queue.add(voucherOrder);
        return Result.ok(orderId);
    }




//    @Override
//    public Result seckillVoucher(Long voucherId) {
//        //	1判断当前时间到了抢购时间没有。
//        SeckillVoucher voucher = query().eq("voucher_id", voucherId).one();
//        LocalDateTime now = LocalDateTime.now();
//        if (!voucher.getBeginTime().isBefore(now)) {
//            return Result.fail("抢购还没开始.......");
//        }
//        if (!voucher.getEndTime().isAfter(now)) {
//            return Result.fail("抢购已经结束.......");
//        }
//        //	2判断库存是否充足。
//        if (voucher.getStock() <= 0) {
//            return Result.fail("优惠卷已经被抢光.......");
//        }
//
//        //	3判断该用户是否已经抢购过该卷。
//        UserDTO user = UserHolder.getUser();
//        RLock lock = redissonClient.getLock(RedisConstants.LOCK_SHOP_KEY + user.getId());
//        boolean b = lock.tryLock();
//        try {
//            //获取代理对象(事务)
//            if (b) return seckillVoucherService.getResult(voucherId, user);
//        } finally {
//            //释放锁
//            lock.unlock();
//        }
//        return Result.fail("抢购失败");
//    }
//    @Resource
//    private RedissonClient redissonClient;
//    @Transactional
//    public Result getResult(Long voucherId, UserDTO user) {
//        VoucherOrder voucherOrder1 = iVoucherOrderService.selectOneByUserIdAndVoucherId(user.getId(), voucherId);
//        if (ObjectUtil.isNotEmpty(voucherOrder1)) {
//            return Result.fail("同一张卷限购一次");
//        }
//
//        //	5库存要减一。
//        boolean success = update().setSql("stock=stock-1").eq("voucher_id", voucherId).gt("stock", 0).update();
//        if (!success) {
//            return Result.fail("抢购失败");
//        }
//        //	4订单表生成个订单。
//        Long orderId = voucherOrderServicel.createOrder(voucherId);
//        if (ObjectUtil.isNotEmpty(orderId)) {
//            return Result.ok(orderId);
//        }
//        return null;
//    }
}
